package com.zjdiepu.www.commpent.handler;

import javax.servlet.http.HttpServletRequest;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.TypeMismatchException;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.HttpMediaTypeNotSupportedException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartException;

import com.zjdiepu.www.base.core.ApiResponse;
import com.zjdiepu.www.base.core.BaseException;
import com.zjdiepu.www.base.enums.type.ResultFlagType;
import com.zjdiepu.www.base.lang.HttpClientException;
import com.zjdiepu.www.common.consts.SystemConsts;

@ControllerAdvice(annotations = RestController.class)
public class ApiExceptionHandler {
	private static final Logger logger = LoggerFactory.getLogger(ApiExceptionHandler.class);
	
	@ResponseBody
	@ExceptionHandler(TypeMismatchException.class)
	public ApiResponse handleTypeMismatchException(TypeMismatchException ex) {
		logger.debug("handler TypeMismatchException.", ex);
		return ApiResponse.fail(ResultFlagType.PARAM_TYPE_MISMATCH);
	}

	@ResponseBody
	@ExceptionHandler(HttpMediaTypeNotSupportedException.class)
	public ApiResponse handleHttpMediaTypeNotSupportedException(HttpMediaTypeNotSupportedException ex) {
		logger.debug("handler HttpMediaTypeNotSupportedException.", ex);
		return ApiResponse.fail(ResultFlagType.PARAM_TYPE_MISMATCH);
	}

	@ResponseBody
	@ExceptionHandler(HttpRequestMethodNotSupportedException.class)
	public ApiResponse handleHttpRequestMethodNotSupportedException(HttpRequestMethodNotSupportedException ex) {
		logger.debug("handler HttpRequestMethodNotSupportedException.", ex);
		return ApiResponse.fail(ResultFlagType.HTTP_REQUEST_METHOD_NOT_SUPPORTED);
	}

	@ResponseBody
	@ExceptionHandler(BaseException.class)
	public ApiResponse handleBaseException(BaseException ex, HttpServletRequest request) {
		logger.debug(String.format("请求方法[%1$s]发生异常，[错误代码：%2$s，错误信息：%3$s]", request.getRequestURI(),
				ex.getErrorCode(), ex.getErrorMsg()));
		if(ResultFlagType.ACCESS_DENIED.getCode().toString().equals(ex.getErrorCode())){
			return  ApiResponse.overdue(ex.getErrorCode(), ex.getErrorMsg());
		} else {
			return  ApiResponse.fail(ex.getErrorCode(), ex.getErrorMsg());
		}
	}
	
	@ResponseBody
	@ExceptionHandler(MethodArgumentNotValidException.class)
	public ApiResponse handleMethodArgumentNotValidException(MethodArgumentNotValidException ex) {
		logger.debug("handler MethodArgumentNotValidException.", ex);
		BindingResult bindingResult = ex.getBindingResult();
		StringBuffer sb = new StringBuffer();

		for (FieldError fieldError : bindingResult.getFieldErrors()) {
			sb.append(fieldError.getDefaultMessage()).append(SystemConsts.NEW_LINE_CHARS);
		}
		String errorMesssage = sb.toString();
		if (errorMesssage.length() > 0) {
			errorMesssage = errorMesssage.substring(0, errorMesssage.length() - SystemConsts.NEW_LINE_CHARS.length());
		}
		return ApiResponse.fail(ResultFlagType.PARAM_INVALID.getCode(), errorMesssage);
	}
	
	@ResponseBody
	@ExceptionHandler(BindException.class)
	public ApiResponse handleBindException(BindException ex) {
		logger.debug("handler MethodArgumentNotValidException.", ex);
		BindingResult bindingResult = ex.getBindingResult();
		StringBuffer sb = new StringBuffer();

		for (FieldError fieldError : bindingResult.getFieldErrors()) {
			sb.append(fieldError.getDefaultMessage()).append(SystemConsts.NEW_LINE_CHARS);
		}
		String errorMesssage = sb.toString();
		if (errorMesssage.length() > 0) {
			errorMesssage = errorMesssage.substring(0, errorMesssage.length() - SystemConsts.NEW_LINE_CHARS.length());
		}
		return ApiResponse.fail(ResultFlagType.PARAM_INVALID.getCode(), errorMesssage);
	}

	@ResponseBody
	@ExceptionHandler(HttpMessageNotReadableException.class)
	public ApiResponse handleHttpMessageNotReadableException(HttpMessageNotReadableException ex) {
		logger.debug("handler HttpMessageNotReadableException.", ex);
		return ApiResponse.fail(ResultFlagType.HTTP_MESSAGE_NOT_READABLE.getCode(), null == ex.getRootCause() ? ex.getMessage() : ex.getRootCause().getMessage());
	}

	@ResponseBody
	@ExceptionHandler(MultipartException.class)
	public ApiResponse handleUploadException(MultipartException ex) {
		logger.debug("handler MultipartException.", ex);
		return ApiResponse.fail(ResultFlagType.HTTP_UPLOAD_SIZE_EXCEEDED);

	}
	
	@ResponseBody
	@ExceptionHandler(HttpClientException.class)
	public ApiResponse handleUnexpectedServerError(HttpClientException ex, HttpServletRequest request) {
		logger.debug(String.format("请求URL[%1$s]发生异常，错误信息：[%2$s]", request.getRequestURI(), ex.getMessage()));
		return ApiResponse.fail(ex.getHttpStatusCode(), ex.getMessage());
	}

	@ResponseBody
	@ExceptionHandler(RuntimeException.class)
	public ApiResponse handleUnexpectedServerError(RuntimeException ex, HttpServletRequest request) {
		logger.debug(String.format("请求URL[%1$s]发生异常，错误信息：[%2$s]", request.getRequestURI(), ex.getMessage()));
		return ApiResponse.fail(ResultFlagType.HTTP_UNEXPECTED_SERVER_ERROR);
	}
}